/* jzc 2020-02-03 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>

// 用于创建唯一的key
#define MSG_FILE "/opt/tfw/av_file" 
/*
 *  Compilation: gcc -Wall ex1.c -o ex1 -lclamav
 *
 *  Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
 *  Copyright (C) 2007 - 2009 Sourcefire, Inc.
 *  Author: Tomasz Kojm <tkojm@clamav.net>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA 02110-1301, USA.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <clamav.h>

/*
 * Exit codes:
 *  0: clean
 *  1: infected
 *  2: error
 */


char _virus_name[4096];
struct cl_engine * engine = NULL;
int scan_file(const char *filename)
{
	int fd, ret;
	unsigned long int size = 0;
	unsigned int sigs = 0;
	long double mb;
    struct cl_scan_options options;
    const char *virname;


    if((fd = open(filename, O_RDONLY)) == -1) {
	printf("Can't open file %s\n", filename);
	return 2;
    }
if(engine == NULL){
    if((ret = cl_init(CL_INIT_DEFAULT)) != CL_SUCCESS) {
	printf("Can't initialize libclamav: %s\n", cl_strerror(ret));
	return 2;
    }

    if(!(engine = cl_engine_new())) {
	printf("Can't create new engine\n");
	return 2;
    }

    /* load all available databases from default directory */
    const char * dir = cl_retdbdir();
    if((ret = cl_load(dir, engine, &sigs, CL_DB_STDOPT)) != CL_SUCCESS) {
	printf("cl_load: %s\n", cl_strerror(ret));
	close(fd);
        cl_engine_free(engine);
	return 2;
    }

    printf("Loaded %u signatures.\n", sigs);

    /* build engine */
    if((ret = cl_engine_compile(engine)) != CL_SUCCESS) {
	printf("Database initialization error: %s\n", cl_strerror(ret));;
        cl_engine_free(engine);
	close(fd);
	return 2;
    }
}
    /* scan file descriptor */
    memset(&options, 0, sizeof(struct cl_scan_options));
    options.parse |= ~0; /* enable all parsers */
    options.general |= CL_SCAN_GENERAL_HEURISTICS; /* enable heuristic alert options */

    if((ret = cl_scandesc(fd, filename, &virname, &size, engine, &options)) == CL_VIRUS) {
	printf("Virus detected: %s\n", virname);
	strcpy(_virus_name, virname);
    } else {
	if(ret == CL_CLEAN) {
	    printf("No virus detected.\n");
	} else {
	    printf("Error: %s\n", cl_strerror(ret));
	    cl_engine_free(engine);
	    close(fd);
	    return 2;
	}
    }
    close(fd);

    /* free memory */
    //cl_engine_free(engine);

    /* calculate size of scanned data */
    mb = size * (CL_COUNT_PRECISION / 1024) / 1024.0;
    printf("Data scanned: %2.2Lf MB\n", mb);

    return ret == CL_VIRUS ? 1 : 0;
}

// 消息构造
struct msg_from {
    long mtype;
    int result;
    char mtext[4096];
};

int main(int argc, char **argv) {
    int msqid;
    key_t key;
    struct msg_from msg;

    int fd=open(MSG_FILE,O_WRONLY|O_CREAT);
    close(fd);
    engine = NULL;
    // 获取key值
    if ((key = ftok(MSG_FILE, 'z')) < 0) {
        perror("ftok error!");
        exit(1);
    }

    // 打印key值
    printf("Message Queue - server key is: %d.\n", key);

    // 创建消息队列
    if ((msqid = msgget(key, IPC_CREAT|0777)) == -1) {
        perror("msgget error");
        exit(1);
    }

    // 打印进程队列ID及进程ID
    printf("My msqid is : %d\n", msqid);
    printf("My pid is : %d\n", getpid());

    // 循环读取消息
	for (;;) {
        msgrcv(msqid, &msg, sizeof(msg.mtext)+sizeof(msg.result), 888, 0); // 返回类型为888的第一个消息
        printf("Server: receive msg.mtext is: %s.\n", msg.mtext);
        printf("Server: receive msg.mtype is: %d.\n", msg.mtype);
	char *virus = NULL;
	int ret = scan_file((const char *)msg.mtext); 

        msg.mtype = 999; //客户端接受的消息
	msg.result = ret;
	if(ret == 1)
	{
		strcpy(msg.mtext, _virus_name);
	}
        msgsnd(msqid, &msg, sizeof(msg.mtext)+sizeof(msg.result), 0);
    }

    return 0;
}






